
#include "alttree.hpp"

Cquad::Cquad(): topl(NULL), topr(NULL), botl(NULL), botr(NULL),
	list(NULL), check(0) {
}

Cquad::~Cquad() {
	kill();
}

/// -------------- deletion ----------------------
void Cquad::kill() {
    check = 0;
	if(topr) {
		if(topr->list) {

			delete topr;
		}
		else topr->kill();
	}
	if(botr) {
		if(botr->list) {
			delete botr;
		}
		else botr->kill();
	}
	if(topl) {
		if(topl->list) {
			delete topl;
		}
		else topl->kill();
	}
	if(botl) {
		if(botl->list) {
			delete topr;
		}
		else botl->kill();
	}
}

/// --------- creation ---------------------------
vec Cquad::doref(vec& ref, vec& mid, short side) {
	switch(side) {
		case 0:
			return mid;
		case 1:
			return (mid.x - ref.x, ref.y);
		case 2:
			return (ref.x, mid.y - ref.y);
		case 3:
			return ref;
	}
}

vec Cquad::domid(vec& ref, vec& mid, short side) {
	switch(side) {
		case 0:
			return mid + (mid - ref) / 2.0;
		case 1:
			return (mid.x + (mid.x - ref.x) / 2.0, (mid.y - ref.y) / 2.0);
		case 2:
			return ((mid.x - ref.x) / 2.0, mid.y + (mid.y - ref.y) / 2.0);
		case 3:
			return (mid - ref) / 2.0;
	}
}

void Cquad::make(point* pptr, vec ref, vec mid, short lv) {
	if(check) {
		switch(mid == pptr->pos) {
			case 0:
				if(!topr) topr = new Cquad;
				topr->make(pptr, doref(ref, mid, 0), domid(ref, mid, 0), lv + 1);
				break;
			case 1:
				if(!botr) botr = new Cquad;
				botr->make(pptr, doref(ref, mid, 1), domid(ref, mid, 1), lv + 1);
				break;
			case 2:
				if(!topl) topl = new Cquad;
				topl->make(pptr, doref(ref, mid, 2), domid(ref, mid, 2), lv + 1);
				break;
			case 3:
				if(!botl) botl = new Cquad;
				botl->make(pptr, doref(ref, mid, 3), domid(ref, mid, 3), lv + 1);
				break;
		}

		if(list) {
			switch(mid == list->pos) {
				case 0:
					if(!topr) topr = new Cquad;
					topr->make(list, doref(ref, mid, 0), domid(ref, mid, 0), lv + 1);
					break;
				case 1:
					if(!botr) botr = new Cquad;
					botr->make(list, doref(ref, mid, 1), domid(ref, mid, 1), lv + 1);
					break;
				case 2:
					if(!topl) topl = new Cquad;
					topl->make(list, doref(ref, mid, 2), domid(ref, mid, 2), lv + 1);
					break;
				case 3:
					if(!botl) botl = new Cquad;
					botl->make(list, doref(ref, mid, 3), domid(ref, mid, 3), lv + 1);
					break;
			}
			list = NULL;
		}
	}
	else {
		list = pptr;
		check = 1;
	}
}

/// --------------- searching --------------------
point* Cquad::find(const vec& mouse, vec ref, vec mid) {
	if(list) return list;
	else {
		switch(mid == mouse) {
			case 0:
				if(topr) {
					topr->find(mouse, doref(ref, mid, 0), domid(ref, mid, 0));
				}
				else return NULL;
			case 1:
				if(botr) {
					botr->find(mouse, doref(ref, mid, 1), domid(ref, mid, 1));
				}
				else return NULL;
			case 2:
				if(topl) {
					topl->find(mouse, doref(ref, mid, 2), domid(ref, mid, 2));
				}
				else return NULL;
			case 3:
				if(botl) {
					botl->find(mouse, doref(ref, mid, 3), domid(ref, mid, 3));
				}
				else return NULL;
		}
	}
}

